package com.atguigu.gmall.product.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.cache.GmallCache;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.ManageService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author Fxz
 * @version 1.0
 * @date 2022-02-04 16:06
 */
@SuppressWarnings("all")
@Service
@RequiredArgsConstructor
public class ManageServiceImpl implements ManageService {

	private final RabbitService rabbitService;

	private final RedissonClient redissonClient;

	private final RedisTemplate<Object, Object> redisTemplate;

	private final BaseTrademarkMapper baseTrademarkMapper;

	private final SpuInfoMapper spuInfoMapper;

	private final SpuImageMapper spuImageMapper;

	private final SpuSaleAttrMapper spuSaleAttrMapper;

	private final SpuSaleAttrValueMapper spuSaleAttrValueMapper;

	private final SkuInfoMapper skuInfoMapper;

	private final SkuImageMapper skuImageMapper;

	private final SkuSaleAttrValueMapper skuSaleAttrValueMapper;

	private final SkuAttrValueMapper skuAttrValueMapper;

	private final BaseSaleAttrMapper baseSaleAttrMapper;

	private final BaseAttrInfoMapper baseAttrInfoMapper;

	private final BaseAttrValueMapper baseAttrValueMapper;

	private final BaseCategory1Mapper baseCategory1Mapper;

	private final BaseCategory2Mapper baseCategory2Mapper;

	private final BaseCategory3Mapper baseCategory3Mapper;

	private final BaseCategoryViewMapper baseCategoryViewMapper;

	/**
	 * 获取所有一级分类数据
	 * @return 一级分类数据
	 */
	@Override
	public List<BaseCategory1> getBaseCategory1() {
		return baseCategory1Mapper.selectList(null);
	}

	/**
	 * 根据一级分类id获取二级分类数据
	 * @param category1Id 一级分类id
	 * @return 二级分类数据
	 */
	@Override
	public List<BaseCategory2> getBaseCategory2(Long category1Id) {
		return baseCategory2Mapper
				.selectList(Wrappers.<BaseCategory2>query().lambda().eq(BaseCategory2::getCategory1Id, category1Id));
	}

	/**
	 * 根据二级分类id获取所有三级分类数据
	 * @param category2Id 二级分类id
	 * @return 三级分类数据
	 */
	@Override
	public List<BaseCategory3> getBaseCategory3(Long category2Id) {
		return baseCategory3Mapper
				.selectList(Wrappers.<BaseCategory3>query().lambda().eq(BaseCategory3::getCategory2Id, category2Id));
	}

	/**
	 * 根据分类id 获取平台属性列表
	 * @param category1Id 一级分类id
	 * @param category2Id 二级分类id
	 * @param category3Id 三级分类id
	 * @return 平台属性值
	 */
	@Override
	public List<BaseAttrInfo> getBaseAttrInfo(Long category1Id, Long category2Id, Long category3Id) {
		return baseAttrInfoMapper.selectAttrInfoList(category1Id, category2Id, category3Id);
	}

	/**
	 * 保存平台属性/修改
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void saveAttrInfo(BaseAttrInfo baseAttrInfo) {

		if (baseAttrInfo.getId() != null) {
			baseAttrInfoMapper.updateById(baseAttrInfo);
			baseAttrValueMapper.delete(
					Wrappers.<BaseAttrValue>query().lambda().eq(BaseAttrValue::getAttrId, baseAttrInfo.getId()));
		}
		else {
			baseAttrInfoMapper.insert(baseAttrInfo);
		}

		List<BaseAttrValue> attrValueList = baseAttrInfo.getAttrValueList();
		if (CollectionUtils.isNotEmpty(attrValueList)) {
			attrValueList.forEach(item -> {
				item.setAttrId(baseAttrInfo.getId());
				baseAttrValueMapper.insert(item);
			});
		}
	}

	/**
	 * 根据平台属性id获取平台属性值集合
	 */
	@Override
	public List<BaseAttrValue> getAttrValueList(Long attrId) {
		if (ObjectUtils.isNotEmpty(baseAttrInfoMapper.selectById(attrId))) {
			return baseAttrValueMapper
					.selectList(Wrappers.<BaseAttrValue>query().lambda().eq(BaseAttrValue::getAttrId, attrId));
		}
		return Collections.emptyList();
	}

	/**
	 * 跟据三级分类id分页查询spu
	 */
	@Override
	public IPage<SpuInfo> getSpuInfoList(Page<SpuInfo> spuInfoPage, SpuInfo spuInfo) {
		return spuInfoMapper.selectPage(spuInfoPage, Wrappers.<SpuInfo>query().lambda()
				.eq(SpuInfo::getCategory3Id, spuInfo.getCategory3Id()).orderByDesc(SpuInfo::getId));
	}

	/**
	 * 获取所有销售属性列表
	 */
	@Override
	public List<BaseSaleAttr> getBaseSaleAttrList() {
		return baseSaleAttrMapper.selectList(null);
	}

	/**
	 * 保存spu信息 1.spu_info 2.spu_image 3.spu_sale_attr 4.spu_sale_attr_value
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean saveSpuInfo(SpuInfo spuInfo) {
		spuInfoMapper.insert(spuInfo);

		List<SpuImage> spuImageList = spuInfo.getSpuImageList();
		if (CollectionUtils.isNotEmpty(spuImageList)) {
			spuImageList.forEach(item -> {
				item.setSpuId(spuInfo.getId());
				spuImageMapper.insert(item);
			});
		}

		List<SpuSaleAttr> spuSaleAttrList = spuInfo.getSpuSaleAttrList();
		if (CollectionUtils.isNotEmpty(spuSaleAttrList)) {
			spuSaleAttrList.forEach(item -> {
				item.setSpuId(spuInfo.getId());
				spuSaleAttrMapper.insert(item);

				List<SpuSaleAttrValue> spuSaleAttrValueList = item.getSpuSaleAttrValueList();
				if (CollectionUtils.isNotEmpty(spuSaleAttrValueList)) {
					spuSaleAttrValueList.forEach(value -> {
						value.setSpuId(spuInfo.getId());
						value.setSaleAttrName(item.getSaleAttrName());
						spuSaleAttrValueMapper.insert(value);
					});
				}
			});
		}
		return Boolean.TRUE;
	}

	/**
	 * 跟据spuId查询spuImage列表
	 */
	@Override
	public List<SpuImage> getSpuImageList(Long spuId) {
		return spuImageMapper.selectList(Wrappers.<SpuImage>query().lambda().eq(SpuImage::getSpuId, spuId));
	}

	/**
	 * 跟据spuId查询spu对应的销售属性以及销售属性值
	 */
	@Override
	public List<SpuSaleAttr> getSpuSaleAttrList(Long spuId) {
		return spuSaleAttrMapper.selectSpuSaleAttrList(spuId);
	}

	/**
	 * 保存skuInfo 1. sku_info 2. sku_attr_value 3. sku_sale_attr_value 4. sku_image
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean saveSkuInfo(SkuInfo skuInfo) {
		skuInfoMapper.insert(skuInfo);

		List<SkuAttrValue> skuAttrValueList = skuInfo.getSkuAttrValueList();
		if (CollectionUtils.isNotEmpty(skuAttrValueList)) {
			skuAttrValueList.forEach(item -> {
				item.setSkuId(skuInfo.getId());
				skuAttrValueMapper.insert(item);
			});
		}

		List<SkuSaleAttrValue> skuSaleAttrValueList = skuInfo.getSkuSaleAttrValueList();
		if (CollectionUtils.isNotEmpty(skuSaleAttrValueList)) {
			skuSaleAttrValueList.forEach(item -> {
				item.setSkuId(skuInfo.getId());
				item.setSpuId(skuInfo.getSpuId());
				skuSaleAttrValueMapper.insert(item);
			});
		}

		List<SkuImage> skuImageList = skuInfo.getSkuImageList();
		if (CollectionUtils.isNotEmpty(skuImageList)) {
			skuImageList.forEach(item -> {
				item.setSkuId(skuInfo.getId());
				skuImageMapper.insert(item);
			});
		}

		return Boolean.TRUE;
	}

	/**
	 * 分页查询skuInfo
	 */
	@Override
	public IPage<SkuInfo> getSkuInfoList(Page<SkuInfo> skuInfoPage) {
		return skuInfoMapper.selectPage(skuInfoPage, Wrappers.<SkuInfo>query().lambda().orderByDesc(SkuInfo::getId));
	}

	/**
	 * 商品上架
	 */
	@Override
	public Boolean onSale(Long skuId) {
		// 向mq发送消息
		rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_GOODS, MqConst.ROUTING_GOODS_UPPER, skuId);

		SkuInfo skuInfo = new SkuInfo();
		skuInfo.setId(skuId);
		skuInfo.setIsSale(1);
		return skuInfoMapper.updateById(skuInfo) > 0;
	}

	/**
	 * 商品下架
	 */
	@Override
	public Boolean cancelSale(Long skuId) {
		// 向mq发送消息
		rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_GOODS, MqConst.ROUTING_GOODS_LOWER, skuId);

		SkuInfo skuInfo = new SkuInfo();
		skuInfo.setId(skuId);
		skuInfo.setIsSale(0);
		return skuInfoMapper.updateById(skuInfo) > 0;
	}

	/**
	 * 跟据skuId 查询skuInfo以及skuImageList 采用分布式锁处理
	 */
	@GmallCache(prefix = RedisConst.SKUKEY_PREFIX)
	@Override
	public SkuInfo getSkuInfo(Long skuInfoId) {
		return getSkuInfoByDb(skuInfoId);
	}

	/**
	 * 采用redisson分布式锁的方式获取skuInfo
	 */
	private SkuInfo getSkuInfoByRedisson(Long skuInfoId) {
		try {
			// 从缓存获取数据
			String skuKey = RedisConst.SKUKEY_PREFIX + skuInfoId + RedisConst.SKUKEY_SUFFIX;
			SkuInfo skuInfo = (SkuInfo) redisTemplate.opsForValue().get(skuKey);

			// 判断缓存中数据是否为空 空的话查数据库
			return Optional.ofNullable(skuInfo).orElseGet(() -> {
				// 数据为空 则加锁 查数据库
				RLock lock = redissonClient.getLock(RedisConst.SKUKEY_PREFIX + skuInfoId + RedisConst.SKULOCK_SUFFIX);
				try {
					boolean flag = lock.tryLock(RedisConst.SKULOCK_EXPIRE_PX1, RedisConst.SKULOCK_EXPIRE_PX2,
							TimeUnit.SECONDS);
					// 加锁成功
					if (flag) {
						// 查询数据库
						SkuInfo skuInfoByDb = getSkuInfoByDb(skuInfoId);
						// 先将值设置进缓存并设置较长时间
						redisTemplate.opsForValue().set(skuKey, skuInfoByDb, RedisConst.SKUKEY_TIMEOUT,
								TimeUnit.SECONDS);
						// 然后判断数据是否为空 为空的话new一个空对象并设置进缓存 覆盖上面的缓存 设置较短过期时间
						return Optional.ofNullable(skuInfoByDb).orElseGet(() -> {
							SkuInfo info = new SkuInfo();
							redisTemplate.opsForValue().set(skuKey, info, RedisConst.SKUKEY_TEMPORARY_TIMEOUT,
									TimeUnit.SECONDS);
							return info;
						});
					}
					else {
						// 没有获取到锁 等待100ms 进行自选
						Thread.sleep(100);
						return getSkuInfo(skuInfoId);
					}
				}
				catch (InterruptedException e) {
					e.printStackTrace();
					return new SkuInfo();
				}
				finally {
					lock.unlock();
				}
			});
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return getSkuInfoByDb(skuInfoId);
	}

	/**
	 * 跟据skuInfoId查询skuInfo
	 */
	private SkuInfo getSkuInfoByDb(Long skuInfoId) {
		SkuInfo sku = skuInfoMapper.selectById(skuInfoId);
		List<SkuImage> skuImages = skuImageMapper
				.selectList(Wrappers.<SkuImage>query().lambda().eq(SkuImage::getSkuId, skuInfoId));
		// 避免空指针异常
		Optional.ofNullable(sku).ifPresent(item -> item.setSkuImageList(skuImages));
		return sku;
	}

	/**
	 * 跟据三级分类id获取分类信息
	 */
	@GmallCache(prefix = "categoryViewByCategory3Id")
	@Override
	public BaseCategoryView getCategoryViewByCategory3Id(Long category3Id) {
		return baseCategoryViewMapper.selectById(category3Id);
	}

	/**
	 * 跟据skuId查询商品价格
	 */
	@GmallCache(prefix = "skuPrice")
	@Override
	public BigDecimal getSkuPrice(Long skuId) {
		return Optional.ofNullable(skuInfoMapper.selectById(skuId)).orElse(new SkuInfo().setPrice(BigDecimal.ZERO))
				.getPrice();
	}

	/**
	 * 跟据spuId和skuId查询销售属性和销售属性值
	 */
	@GmallCache(prefix = "spuSaleAttrListCheckBySku")
	@Override
	public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long spuId, Long skuId) {
		return spuSaleAttrMapper.selectSpuSaleAttrListCheckBySku(spuId, skuId);
	}

	/**
	 * 跟据spuId获取skuId和销售属性id的组合
	 */
	@GmallCache(prefix = "skuValueIdsMap")
	@Override
	public Map<Object, Object> getSkuValueIdsMap(Long spuId) {
		Map<Object, Object> result = new HashMap<>();

		List<Map<String, Object>> listMap = skuSaleAttrValueMapper.selectSaleAttrValueBySpu(spuId);
		if (CollectionUtils.isNotEmpty(listMap)) {
			listMap.forEach(item -> result.put(item.get("value_ids"), item.get("sku_id")));
		}

		return result;
	}

	/**
	 * 获取全部分类信息
	 */
	@GmallCache(prefix = "baseCategoryList")
	@Override
	public List<JSONObject> getBaseCategoryList() {
		List<JSONObject> res = new LinkedList<>();
		AtomicReference<Integer> index = new AtomicReference<>(0);
		// 查询所有分类数据
		List<BaseCategoryView> baseCategoryViews = baseCategoryViewMapper.selectList(null);
		// 跟据一级分类id分组
		Map<Long, List<BaseCategoryView>> category1Map = baseCategoryViews.stream()
				.collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));

		Set<Map.Entry<Long, List<BaseCategoryView>>> entries1 = category1Map.entrySet();
		entries1.forEach(item -> {
			index.getAndSet(index.get() + 1);
			// key: 一级分类id
			Long category1Id = item.getKey();
			// 一级分类对应的value
			List<BaseCategoryView> category2List = item.getValue();
			// 一级分类名
			String category1Name = category2List.get(0).getCategory1Name();
			// 创建json对象
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("index", index.get());
			jsonObject.put("categoryName", category1Name);
			jsonObject.put("categoryId", category1Id);

			List<JSONObject> list = new LinkedList<>();
			// 获取二级分类数据
			Map<Long, List<BaseCategoryView>> category2Map = category2List.stream()
					.collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
			Set<Map.Entry<Long, List<BaseCategoryView>>> entries2 = category2Map.entrySet();
			entries2.forEach(item2 -> {
				// key: 二级分类id
				Long category2Id = item2.getKey();
				// 二级分类对应的value
				List<BaseCategoryView> category3List = item2.getValue();
				// 二级分类名
				String category2Name = category3List.get(0).getCategory1Name();

				List<JSONObject> objectList = new LinkedList<>();
				// 获取三级分类数据
				category3List.forEach(category -> {
					JSONObject object = new JSONObject();
					object.put("categoryName", category.getCategory3Name());
					object.put("categoryId", category.getCategory3Id());
					objectList.add(object);
				});

				// 创建json对象
				JSONObject jsonObject2 = new JSONObject();
				jsonObject2.put("categoryName", category2Name);
				jsonObject2.put("categoryId", category2Id);
				jsonObject2.put("categoryChild", objectList);
				list.add(jsonObject2);
			});
			jsonObject.put("categoryChild", list);
			res.add(jsonObject);
		});
		return res;
	}

	/**
	 * 跟据品牌id获取品牌信息
	 */
	@Override
	public BaseTrademark getTrademark(Long tmId) {
		return baseTrademarkMapper.selectById(tmId);
	}

	/**
	 * 跟据skuId查询平台属性
	 */
	@Override
	public List<BaseAttrInfo> getAttrList(Long skuId) {
		return baseAttrInfoMapper.selectBaseAttrInfoListBySkuId(skuId);
	}

}
